<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/jexo/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/jexo/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/jexo/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/jexo/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/jexo/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/jexo/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/jexo/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Android,Android底层," />










<meta name="description" content="一直想深入Android底层开发，首先就从写一个完整的HAL层开发demo开始吧，步骤确实有很多，对我们这种不熟悉c/c++开发的人来说，确实是很痛苦，我看这简单的demo都要理解半天。下面我就一步步的来实现HAL层开发，附代码。 我这里简单的归纳了下，一共8大步骤  linux驱动实现 驱动测试 hal层实现 aidl实现 service java实现 service jni 实现 注册serv">
<meta name="keywords" content="Android,Android底层">
<meta property="og:type" content="article">
<meta property="og:title" content="Android HAL层开发">
<meta property="og:url" content="http://ja_project.gitee.io/jexo/2018/04/18/Android HAL层开发/index.html">
<meta property="og:site_name" content="Ling Hu Blog">
<meta property="og:description" content="一直想深入Android底层开发，首先就从写一个完整的HAL层开发demo开始吧，步骤确实有很多，对我们这种不熟悉c/c++开发的人来说，确实是很痛苦，我看这简单的demo都要理解半天。下面我就一步步的来实现HAL层开发，附代码。 我这里简单的归纳了下，一共8大步骤  linux驱动实现 驱动测试 hal层实现 aidl实现 service java实现 service jni 实现 注册serv">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-69ce7f3525d48920.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-a69082ccd1fb3ed4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-681d1e7adae9bf28.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-2ba5972a38c9ab7c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-3ee75f15e18eec20.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-c156ebe3ca4d88e8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-2d84435f7d668d5b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-c93addff6ce42e43.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-3b10a3edbf090d7e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-0f8fdfed2f1b30a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-54d9d561a5df8b38.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4241874-a8a63eb4410946e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:updated_time" content="2018-04-18T13:23:33.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Android HAL层开发">
<meta name="twitter:description" content="一直想深入Android底层开发，首先就从写一个完整的HAL层开发demo开始吧，步骤确实有很多，对我们这种不熟悉c/c++开发的人来说，确实是很痛苦，我看这简单的demo都要理解半天。下面我就一步步的来实现HAL层开发，附代码。 我这里简单的归纳了下，一共8大步骤  linux驱动实现 驱动测试 hal层实现 aidl实现 service java实现 service jni 实现 注册serv">
<meta name="twitter:image" content="http://upload-images.jianshu.io/upload_images/4241874-69ce7f3525d48920.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/jexo/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://ja_project.gitee.io/jexo/2018/04/18/Android HAL层开发/"/>





  <title>Android HAL层开发 | Ling Hu Blog</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?abc8796c232e2b898d516245257842b4";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/jexo/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Ling Hu Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/jexo/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/jexo/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/jexo/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/jexo/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/jexo/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://ja_project.gitee.io/jexo/jexo/2018/04/18/Android HAL层开发/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Ling Hu">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/jexo/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Ling Hu Blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Android HAL层开发</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-04-18T20:57:40+08:00">
                2018-04-18
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/jexo/categories/Android底层/" itemprop="url" rel="index">
                    <span itemprop="name">Android底层</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/jexo/2018/04/18/Android HAL层开发/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count gitment-comments-count" data-xid="/jexo/2018/04/18/Android HAL层开发/" itemprop="commentsCount"></span>
                </a>
              </span>
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>一直想深入Android底层开发，首先就从写一个完整的HAL层开发demo开始吧，步骤确实有很多，对我们这种不熟悉c/c++开发的人来说，确实是很痛苦，我看这简单的demo都要理解半天。下面我就一步步的来实现HAL层开发，附代码。</p>
<p>我这里简单的归纳了下，一共8大步骤</p>
<ol>
<li>linux驱动实现</li>
<li>驱动测试</li>
<li>hal层实现</li>
<li>aidl实现</li>
<li>service java实现</li>
<li>service jni 实现</li>
<li>注册service和jni方法</li>
<li>android app调用测试</li>
</ol>
<a id="more"></a>
<p>下面我一步步实现。</p>
<pre><code>开发环境：Ubuntu 14.04
        Android源码 2.3.1
        内核 2.6.9
</code></pre><h3 id="linux驱动实现"><a href="#linux驱动实现" class="headerlink" title="linux驱动实现"></a>linux驱动实现</h3><p>下面我就简单实现一个字符驱动<br><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Created by javalong on 17/3/24.</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/module.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/init.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/fs.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/cdev.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/kernel.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/slab.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;asm/uaccess.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/proc_fs.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/device.h&gt;</span></span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">test2_cdev</span>&#123;</span></span><br><span class="line">    <span class="keyword">char</span> val;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">cdev</span> <span class="title">cv</span>;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">dev_t</span> devNo2;</span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">test2_cdev</span> *<span class="title">test2_c</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">test2_open</span> <span class="params">(struct inode *node, struct file *filp)</span></span>&#123;</span><br><span class="line">    <span class="comment">//获取到当前自定义结构体变量，保存至file中，以便其他函数方便访问</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">test2_cdev</span> *<span class="title">n_cdev</span> = <span class="title">container_of</span>(<span class="title">node</span>-&gt;<span class="title">i_cdev</span>,<span class="title">struct</span> <span class="title">test2_cdev</span>,<span class="title">cv</span>);</span></span><br><span class="line">    filp-&gt;private_data = n_cdev;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">test2_release</span> <span class="params">(struct inode *node, struct file *filp)</span></span>&#123;</span><br><span class="line">    filp-&gt;private_data = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">ssize_t</span> test2_read (struct file *filp, <span class="keyword">char</span> __user *buf, <span class="keyword">size_t</span> len, <span class="keyword">loff_t</span> *pos)&#123;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">test2_cdev</span> *<span class="title">n_cdev</span> = (<span class="title">struct</span> <span class="title">test2_cdev</span> *)<span class="title">filp</span>-&gt;<span class="title">private_data</span>;</span></span><br><span class="line">    <span class="keyword">int</span> err;</span><br><span class="line">    printk(<span class="string">"test2 read %c  count : %d"</span>,n_cdev-&gt;val, <span class="keyword">sizeof</span>(n_cdev-&gt;val));</span><br><span class="line">    <span class="keyword">if</span>(copy_to_user(buf,&amp;n_cdev-&gt;val, <span class="keyword">sizeof</span>(n_cdev-&gt;val)))&#123;</span><br><span class="line">        err = -EFAULT;</span><br><span class="line">        <span class="keyword">return</span> err;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">sizeof</span>(n_cdev-&gt;val);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">ssize_t</span> test2_write (struct file *filp, <span class="keyword">const</span> <span class="keyword">char</span> __user *buf, <span class="keyword">size_t</span> len, <span class="keyword">loff_t</span> *pos)&#123;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">test2_cdev</span> *<span class="title">n_cdev</span> = (<span class="title">struct</span> <span class="title">test2_cdev</span> *)<span class="title">filp</span>-&gt;<span class="title">private_data</span>;</span></span><br><span class="line">    <span class="keyword">int</span> err;</span><br><span class="line">    printk(<span class="string">"test2 write %s  count : %d"</span>,(*buf),len);</span><br><span class="line">    <span class="keyword">if</span>(copy_from_user(&amp;n_cdev-&gt;val,buf,len))&#123;</span><br><span class="line">        err = -EFAULT;</span><br><span class="line">        <span class="keyword">return</span> err;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">sizeof</span>(n_cdev-&gt;val);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">file_operations</span> <span class="title">test2_op</span> = &#123;</span></span><br><span class="line">    .owner = THIS_MODULE,</span><br><span class="line">    .open  = test2_open,</span><br><span class="line">    .release = test2_release,</span><br><span class="line">    .write = test2_write,</span><br><span class="line">    .read = test2_read</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">test2_init</span><span class="params">(<span class="keyword">void</span>)</span></span>&#123;</span><br><span class="line">    <span class="comment">//申请设备号，自动分配 fs.h</span></span><br><span class="line">    <span class="keyword">int</span> err = alloc_chrdev_region(&amp;devNo2,<span class="number">0</span>,<span class="number">1</span>,<span class="string">"test2"</span>);</span><br><span class="line">    <span class="keyword">if</span>(err)&#123;</span><br><span class="line">        printk(<span class="string">"获取设备号失败～ %d"</span>,err);</span><br><span class="line">        <span class="keyword">return</span> err;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//申请自定义结构体内存 slab.h</span></span><br><span class="line">    test2_c = kmalloc(<span class="keyword">sizeof</span>(struct test2_cdev),GFP_KERNEL);</span><br><span class="line">    <span class="comment">//初始化 字符设备</span></span><br><span class="line">    cdev_init(&amp;test2_c-&gt;cv,&amp;test2_op);</span><br><span class="line">    <span class="comment">//添加字符设备</span></span><br><span class="line">    err = cdev_add(&amp;test2_c-&gt;cv,devNo2,<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">if</span>(err)&#123;</span><br><span class="line">        printk(<span class="string">"添加设备失败～ %d"</span>,err);</span><br><span class="line">        <span class="keyword">return</span> err;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    test2_c-&gt;val = <span class="string">'8'</span>;</span><br><span class="line">    <span class="comment">//在/dev中创建节点</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">class</span> * <span class="title">cls</span> = <span class="title">class_create</span>(<span class="title">THIS_MODULE</span>,"<span class="title">test2</span>");</span></span><br><span class="line">    device_create(cls,<span class="literal">NULL</span>,devNo2,<span class="literal">NULL</span>,<span class="string">"test2"</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">test2_exit</span><span class="params">(<span class="keyword">void</span>)</span></span>&#123;</span><br><span class="line">    <span class="comment">//释放设备号</span></span><br><span class="line">    unregister_chrdev_region(devNo2,<span class="number">1</span>);</span><br><span class="line">    <span class="comment">//释放自定义结构体的内存</span></span><br><span class="line">    kfree(test2_c);</span><br><span class="line">    <span class="comment">//移除字符设备</span></span><br><span class="line">    cdev_del(&amp;test2_c-&gt;cv);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">module_init(test2_init);</span><br><span class="line">module_exit(test2_exit);</span><br></pre></td></tr></table></figure></p>
<h4 id="代码编译"><a href="#代码编译" class="headerlink" title="代码编译"></a>代码编译</h4><p>在kernel/goldfish/drivers/下创建驱动文件夹，这里我创建<code>test2</code>,<br>然后编写对应的Kconfig/Makefile文件。这2个文件比较简单。<br>Kconfig:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">config TEST2</span><br><span class="line">    tristate &apos;TEST2 Driver&apos;</span><br><span class="line">    default n</span><br></pre></td></tr></table></figure></p>
<p>Makefile:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">obj-$(CONFIG_TEST2) += test2.o</span><br></pre></td></tr></table></figure></p>
<p>把这2个文件都放在test2目录下。</p>
<p>当然仅仅这样还不够，因为你并没有让内核编译关联到我们新创建的test2驱动。</p>
<p>在kernel/goldfish/drivers/Makefile中添加</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-69ce7f3525d48920.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="4FC0D48C-4556-475A-BF46-4D11F38EFB7C.png"></p>
<p>在kernel/goldfish/arch/arm/Kconfig中添加</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-a69082ccd1fb3ed4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="154A0CCE-5B28-4F5F-AE05-61FB90370921.png"></p>
<p>然后在kernel/goldfish下执行命令<code>make menuconfig</code></p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-681d1e7adae9bf28.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="3.png"></p>
<p>然后找到对应的驱动，按键按<code>Y</code>,启动该驱动，然后<code>exit</code>退出保存。</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-2ba5972a38c9ab7c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="4.png"></p>
<p>最后执行,make.</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-3ee75f15e18eec20.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="5.png"></p>
<p>成功生成zImage文件</p>
<h4 id="查看驱动"><a href="#查看驱动" class="headerlink" title="查看驱动"></a>查看驱动</h4><p>启动android虚拟机，并指定内核为当前生成的内核。</p>
<p>emulator -kernel kernel/goldfish/arch/arm/boot/zImage</p>
<p>然后执行adb shell进入android系统控制台</p>
<p>执行 cat /proc/devices</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-c156ebe3ca4d88e8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="6.png"></p>
<p>可以看到test2驱动已经注册了。</p>
<p>但是，我们还希望能在/dev下有test2驱动，那么还需要在test_init最后面再添加2行代码。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">class</span> *<span class="title">cls</span> = <span class="title">class_create</span>(<span class="title">THIS_MODULE</span>,"<span class="title">test2</span>");</span></span><br><span class="line">device_create(cls,<span class="literal">NULL</span>,devNo2,<span class="literal">NULL</span>,<span class="string">"test2"</span>);</span><br></pre></td></tr></table></figure>
<p>然后替换掉原来的test2.c文件，重新make生成zImage文件，然后再调用<br>emulator -kernel kernel/goldfish/arch/arm/boot/zImage  重新启动模拟器<br>就会发现，/dev下出现了test2驱动。</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-2d84435f7d668d5b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="7.png"></p>
<pre><code>注意：如果调用emulator启动android模拟器的时候发现一直黑屏，无法启动，就说明可能是你的驱动编写出错了，导致android系统无法正常启动，你就需要认真检查下代码了。
</code></pre><h3 id="驱动测试"><a href="#驱动测试" class="headerlink" title="驱动测试"></a>驱动测试</h3><p>既然驱动已经编写完毕，那么我们需要编写一个可执行文件，去访问一下驱动是否能正常运行，因为在我们后面的代码中，其实我们是直接在app中通过Service去访问Hal层，然后Hal层再调用底层驱动，所以我们必须保证驱动是正常的，否者到了整个过程都完成后，发现没有正常运行，会很难调试的。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;fcntl.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span>&#123;</span><br><span class="line">    <span class="keyword">char</span> val = <span class="string">'1'</span>;</span><br><span class="line">    <span class="keyword">int</span> fd = open(<span class="string">"/dev/test2"</span>,O_RDWR);</span><br><span class="line">    read(fd,&amp;val,<span class="number">1</span>);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"test04 read %c\n"</span>,val);</span><br><span class="line">    val = val+<span class="number">1</span>;</span><br><span class="line">    write(fd,&amp;val,<span class="number">1</span>);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"test04 write %c\n"</span>,val);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="代码编译-1"><a href="#代码编译-1" class="headerlink" title="代码编译"></a>代码编译</h4><p>需要编译成可执行文件，然后编译成system.img，然后启动虚拟机。<br>Android.mk<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">LOCAL_PATH := $(call my-dir)</span><br><span class="line">include $(CLEAR_VARS)</span><br><span class="line">LOCAL_MODULE_TAGS := optional</span><br><span class="line">LOCAL_SRC_FILES := test_test2.c</span><br><span class="line">LOCAL_MODULE := test_test2</span><br><span class="line">include $(BUILD_EXECUTABLE)</span><br></pre></td></tr></table></figure></p>
<p>然后在external文件夹下新建test2,把Android.mk和test_test2.c这2个文件放入，然后使用<code>mmm</code>编译成可执行模块。</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-c93addff6ce42e43.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="屏幕快照 2017-03-27 14.57.54.png"></p>
<p>编译成功后，如图，会安装至<code>out/target/product/generic/system/bin</code></p>
<p>然后使用<code>make snod</code>生成新的system.img,然后再启动android模拟器。</p>
<p>然后控制台输入<code>adb shell</code>进入Android控制台。然后执行我们刚才生成的test_test2可执行文件。</p>
<p>效果就是把驱动里面保存的char读出来，然后＋1再写入，如果驱动没有错误的话，则如下运行</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-3b10a3edbf090d7e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="屏幕快照 2017-03-27 15.04.49.png"></p>
<h3 id="HAL层实现"><a href="#HAL层实现" class="headerlink" title="HAL层实现"></a>HAL层实现</h3><p>test2.h<br><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Created by javalong on 17/3/25.</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> ANDROIDDRIVER_TEST2_H</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> ANDROIDDRIVER_TEST2_H</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;hardware/hardware.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">test2_module_t</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">hw_module_t</span> <span class="title">common</span>;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">test2_device_t</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">hw_device_t</span> <span class="title">common</span>;</span></span><br><span class="line">    <span class="keyword">int</span> fd;</span><br><span class="line">    <span class="keyword">int</span> (*get_val)(struct <span class="keyword">test2_device_t</span> *dev,<span class="keyword">int</span> *val);</span><br><span class="line">    <span class="keyword">int</span> (*set_val)(struct <span class="keyword">test2_device_t</span> *dev,<span class="keyword">int</span> val);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">test2_dri_open</span><span class="params">(<span class="keyword">const</span> struct <span class="keyword">hw_module_t</span>* <span class="keyword">module</span>, <span class="keyword">const</span> <span class="keyword">char</span>* id,</span></span></span><br><span class="line"><span class="function"><span class="params">              struct <span class="keyword">hw_device_t</span>** device)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">//ANDROIDDRIVER_TEST2_H</span></span></span><br></pre></td></tr></table></figure></p>
<p>test2.c<br><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Created by javalong on 17/3/25.</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;hardware/hardware.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;fcntl.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;hardware/test2.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cutils/log.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">hw_module_methods_t</span> <span class="title">test2_method</span> = &#123;</span></span><br><span class="line">        open : test2_dri_open</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">test2_module_t</span> <span class="title">HAL_MODULE_INFO_SYM</span> = &#123;</span></span><br><span class="line">        common : &#123;</span><br><span class="line">                tag : HARDWARE_MODULE_TAG,</span><br><span class="line">                version_major : <span class="number">1</span>,</span><br><span class="line">                version_minor : <span class="number">0</span>,</span><br><span class="line">                id : <span class="string">"test2"</span>,</span><br><span class="line">                name : <span class="string">"test2"</span>,</span><br><span class="line">                author : <span class="string">"javalong"</span>,</span><br><span class="line">                methods : &amp;test2_method</span><br><span class="line">        &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">test2_get_val</span><span class="params">(struct <span class="keyword">test2_device_t</span> *dev,<span class="keyword">int</span> *val)</span></span>&#123;</span><br><span class="line">    read(dev-&gt;fd,val, <span class="keyword">sizeof</span>(val));</span><br><span class="line">    LOGI(<span class="string">"test2_get_val  %d"</span>,val);</span><br><span class="line">    <span class="keyword">return</span> val;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">test2_set_val</span><span class="params">(struct <span class="keyword">test2_device_t</span> *dev,<span class="keyword">int</span> val)</span></span>&#123;</span><br><span class="line">    write(dev-&gt;fd,&amp;val, <span class="keyword">sizeof</span>(val));</span><br><span class="line">    LOGI(<span class="string">"test2_set_val  %d"</span>,val);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">test2_close</span><span class="params">(struct <span class="keyword">hw_device_t</span>* device)</span></span>&#123;</span><br><span class="line">  <span class="comment">//关闭文件，释放内存</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">test2_device_t</span> *<span class="title">dev</span> = (<span class="title">struct</span> <span class="title">test2_device_t</span> *)<span class="title">device</span>;</span></span><br><span class="line">    close(dev-&gt;fd);</span><br><span class="line">    <span class="built_in">free</span>(dev);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">test2_dri_open</span><span class="params">(<span class="keyword">const</span> struct <span class="keyword">hw_module_t</span>* <span class="keyword">module</span>, <span class="keyword">const</span> <span class="keyword">char</span>* id,</span></span></span><br><span class="line"><span class="function"><span class="params">            struct <span class="keyword">hw_device_t</span>** device)</span></span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">test2_device_t</span> *<span class="title">dev</span> = <span class="title">malloc</span>(<span class="title">sizeof</span>(<span class="title">struct</span> <span class="title">test2_device_t</span>));</span></span><br><span class="line">    <span class="built_in">memset</span>(dev,<span class="number">0</span>, <span class="keyword">sizeof</span>(struct <span class="keyword">test2_device_t</span>));</span><br><span class="line">    dev-&gt;common.tag = HARDWARE_DEVICE_TAG;</span><br><span class="line">    dev-&gt;common.version = <span class="number">0</span>;</span><br><span class="line">    dev-&gt;common.<span class="keyword">module</span> = <span class="keyword">module</span>;</span><br><span class="line">    dev-&gt;common.close = test2_close;</span><br><span class="line"></span><br><span class="line">    dev-&gt;get_val = test2_get_val;</span><br><span class="line">    dev-&gt;set_val = test2_set_val;</span><br><span class="line">    *device = dev;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>((dev-&gt;fd = open(<span class="string">"/dev/test2"</span>,O_RDWR))== <span class="number">-1</span>)&#123;</span><br><span class="line">        LOGI(<span class="string">"fail open /dev/test2"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>将test2.h 放入hardware/libhardware/inlcude下，然后再在hardware/libhardware/modules创建test2. 创建Android.mk</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">LOCAL_PATH := $(call my-dir)</span><br><span class="line">include $(CLEAR_VARS)</span><br><span class="line">LOCAL_MODULE_TAGS := optional</span><br><span class="line">LOCAL_SRC_FILES := test2.c</span><br><span class="line">LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw</span><br><span class="line">LOCAL_MODULE := test.default</span><br><span class="line">LOCAL_PRELINK_MODULE := false</span><br><span class="line">LOCAL_SHARED_LIBRARIES := liblog</span><br><span class="line">include $(BUILD_SHARED_LIBRARY)</span><br></pre></td></tr></table></figure>
<p>然后将Android.mk和test2.c放入刚才新建的test2文件夹下。然后执行<code>mmm ./hardware/libhardware/modules/test2/</code></p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-0f8fdfed2f1b30a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="屏幕快照 2017-03-27 15.56.48.png"></p>
<p>这样就代表HAL层已经编译成功。</p>
<h3 id="aidl实现"><a href="#aidl实现" class="headerlink" title="aidl实现"></a>aidl实现</h3><p>我们最终其实要实现的效果是实现一个SystemService，然后可以在自己的app中调用这个SystemService,而这个SystemService是跟我们的app处于不同的进程的，所以就必须要使用AIDL.<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> android.os;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">ITest2Service</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setVal</span><span class="params">(<span class="keyword">int</span> val)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">getVal</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>这一步同样需要编译，把ITest2Service.aidl放入  <code>framework/base/core/java/android/os</code>下</p>
<p>然后在<code>framework/base</code>下的Android.mk添加一行，让编译的时候把这个aidl也一起编译进去。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">LOCAL_SRC_FILES += \</span><br><span class="line">  ...</span><br><span class="line">  ...</span><br><span class="line">core/java/android/os/ITest2Service.aidl</span><br></pre></td></tr></table></figure></p>
<p>也是使用 mmm，我就不过多介绍了。</p>
<p><code>mmm ./frameworks/base/</code></p>
<h3 id="service-java实现"><a href="#service-java实现" class="headerlink" title="service java实现"></a>service java实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.android.server;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> android.os.ITest2Service;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Created by javalong on 17/3/25.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test2Service</span> <span class="keyword">extends</span> <span class="title">ITest2Service</span>.<span class="title">Stub</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> ptr = <span class="number">0</span>;</span><br><span class="line">    Test2Service()&#123;</span><br><span class="line">        ptr = init_test();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getVal</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> getVal_native(ptr);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setVal</span><span class="params">(<span class="keyword">int</span> val)</span></span>&#123;</span><br><span class="line">        setVal_native(ptr,val);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">native</span> <span class="keyword">int</span> <span class="title">init_test</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">native</span> <span class="keyword">int</span> <span class="title">getVal_native</span><span class="params">(<span class="keyword">int</span> ptr)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">native</span> <span class="keyword">void</span> <span class="title">setVal_native</span><span class="params">(<span class="keyword">int</span> ptr,<span class="keyword">int</span> val)</span></span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="service-jni-实现"><a href="#service-jni-实现" class="headerlink" title="service jni 实现"></a>service jni 实现</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Created by javalong on 17/3/27.</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;jni.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"JNIHelp.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;hardware/hardware.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;android_runtime/AndroidRuntime.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;hardware/test2.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;utils/Log.h&gt;</span></span></span><br><span class="line"><span class="keyword">namespace</span> android&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">static</span> jint <span class="title">getVal</span><span class="params">(JNIEnv *env,jobject obj,jint ptr)</span></span>&#123;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">test2_device_t</span> *<span class="title">dev</span> = (<span class="title">struct</span> <span class="title">test2_device_t</span> *)<span class="title">ptr</span>;</span></span><br><span class="line">        <span class="keyword">int</span> val = <span class="number">0</span>;</span><br><span class="line">        dev-&gt;get_val(dev,&amp;val);</span><br><span class="line">        <span class="keyword">return</span> val;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">setVal</span><span class="params">(JNIEnv *env,jobject obj,jint ptr,jint val)</span></span>&#123;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">test2_device_t</span> *<span class="title">dev</span> = (<span class="title">struct</span> <span class="title">test2_device_t</span> *)<span class="title">ptr</span>;</span></span><br><span class="line">        dev-&gt;set_val(dev,val);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">static</span> jint <span class="title">test_init</span><span class="params">(JNIEnv *env,jobject obj)</span></span>&#123;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">test2_module_t</span> *<span class="title">module</span>;</span></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">test2_device_t</span> *<span class="title">device</span>;</span></span><br><span class="line"></span><br><span class="line">        hw_get_module(<span class="string">"test2"</span>,(<span class="keyword">const</span> struct <span class="keyword">hw_module_t</span> **)&amp;<span class="keyword">module</span>);</span><br><span class="line">        <span class="keyword">module</span>-&gt;common.methods-&gt;open(&amp;(<span class="keyword">module</span>-&gt;common),<span class="string">"test2"</span>,(struct <span class="keyword">hw_device_t</span> **)&amp;device);</span><br><span class="line">        <span class="keyword">return</span> (jint)device;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">const</span> JNINativeMethod method_table[] = &#123;</span><br><span class="line">            &#123;<span class="string">"init_test"</span>,<span class="string">"()I"</span>,(<span class="keyword">void</span> *)test_init&#125;,</span><br><span class="line">            &#123;<span class="string">"getVal_native"</span>,<span class="string">"(I)I"</span>,(<span class="keyword">void</span> *)getVal&#125;,</span><br><span class="line">            &#123;<span class="string">"setVal_native"</span>,<span class="string">"(II)V"</span>,(<span class="keyword">void</span> *)setVal&#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">register_Test2_Service</span><span class="params">(JNIEnv *env)</span></span>&#123;</span><br><span class="line">        jniRegisterNativeMethods(env,<span class="string">"com/android/server/Test2Service"</span>,method_table,NELEM(method_table));</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="注册service和jni方法"><a href="#注册service和jni方法" class="headerlink" title="注册service和jni方法"></a>注册service和jni方法</h3><p>上面的service和jni代码写好后，需要在对应的文件中注册。<br>Test2Service需要在<code>framework/base/services/java/com/android/server/SystemServer.java</code>注册</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">   ...</span><br><span class="line">   Slog.i(TAG, <span class="string">"Telephony Registry"</span>);</span><br><span class="line">   ServiceManager.addService(<span class="string">"telephony.registry"</span>, <span class="keyword">new</span> TelephonyRegistry(context));</span><br><span class="line">   ServiceManager.addService(<span class="string">"test2"</span>, <span class="keyword">new</span> Test2Service());</span><br><span class="line">   ...</span><br></pre></td></tr></table></figure>
<p>Test2Service.cpp 需要注册在<code>framework/base/services/jni/onload.cpp</code></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> <span class="function">jint <span class="title">JNI_OnLoad</span><span class="params">(JavaVM* vm, <span class="keyword">void</span>* reserved)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">   ...</span><br><span class="line">   ...</span><br><span class="line">  register_Test2_Service(env);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>还需要在当前目录的Android.mk添加Test2Service.cpp<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">LOCAL_SRC_FILES:= \</span><br><span class="line">...</span><br><span class="line">...</span><br><span class="line">Test2Service.cpp \</span><br><span class="line">...</span><br></pre></td></tr></table></figure></p>
<p>编译,生成新的system.img</p>
<h3 id="android-app调用测试"><a href="#android-app调用测试" class="headerlink" title="android app调用测试"></a>android app调用测试</h3><p>最后一步，写一个简单的app，获取到Test2Service,然后调用其方法。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.example.javalong.myapplication;</span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> com.example.javalong.myapplication;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> android.app.Activity;</span><br><span class="line"><span class="keyword">import</span> android.os.Bundle;</span><br><span class="line"><span class="keyword">import</span> android.view.View;</span><br><span class="line"><span class="keyword">import</span> android.widget.EditText;</span><br><span class="line"><span class="keyword">import</span> android.widget.TextView;</span><br><span class="line"><span class="keyword">import</span> android.os.ITest2Service;</span><br><span class="line"><span class="keyword">import</span> android.widget.Toast;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">Activity</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        <span class="keyword">final</span> ITest2Service testService = ITest2Service.Stub.asInterface(android.os.ServiceManager.getService(<span class="string">"test2"</span>));</span><br><span class="line">        <span class="keyword">final</span> EditText et_set = (EditText) findViewById(R.id.et_set);</span><br><span class="line">        <span class="keyword">final</span> TextView tv_get = (TextView) findViewById(R.id.tv_test);</span><br><span class="line">        findViewById(R.id.bt_getval)</span><br><span class="line">                .setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">                    <span class="meta">@Override</span></span><br><span class="line">                    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                        <span class="keyword">try</span> &#123;</span><br><span class="line">                            Toast.makeText(MainActivity.<span class="keyword">this</span>, <span class="string">"c:"</span>+testService.getVal(), Toast.LENGTH_SHORT).show();</span><br><span class="line">                            tv_get.setText(testService.getVal()+<span class="string">""</span>);</span><br><span class="line">                        &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">                            Toast.makeText(MainActivity.<span class="keyword">this</span>, <span class="string">"b:"</span>+e, Toast.LENGTH_SHORT).show();</span><br><span class="line">                            e.printStackTrace();</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;);</span><br><span class="line"></span><br><span class="line">        findViewById(R.id.bt_setval).setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    testService.setVal(Integer.parseInt(et_set.getText().toString()));</span><br><span class="line">                    Toast.makeText(MainActivity.<span class="keyword">this</span>, <span class="string">"d:"</span>+Integer.parseInt(et_set.getText().toString()), Toast.LENGTH_SHORT).show();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">                    Toast.makeText(MainActivity.<span class="keyword">this</span>, <span class="string">"e:"</span>+e, Toast.LENGTH_SHORT).show();</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>这个app放在<code>packages/experimental/</code>下，然后也是使用<br>mmm编译<br> <code>mmm ./packages/experimental/app/</code></p>
<p>然后使用make snod,生成system.img，最后启动模拟器。</p>
<p>最终终于把整个流程走完了，看下运行效果。</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-54d9d561a5df8b38.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="屏幕快照 2017-03-27 19.13.04.png"></p>
<p>最终的效果应该是setVal 一个4 getVal也应该是一个4，但是当前不对，这是因为<code>/dev/test2</code>驱动</p>
<p><img src="http://upload-images.jianshu.io/upload_images/4241874-a8a63eb4410946e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="屏幕快照 2017-03-27 19.15.27.png"></p>
<p>是不允许外部直接访问的，所以需要重新给该驱动设置权限。</p>
<p>由于篇幅太大了，我给个链接参考下<br><a href="http://www.cnblogs.com/LoongEmbedded/p/5298388.html" target="_blank" rel="noopener">http://www.cnblogs.com/LoongEmbedded/p/5298388.html</a></p>
<p>最终重新启动模拟器就可以达到目标的效果了。</p>

      
    </div>
    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>Donate comment here</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/jexo/images/wechatpay.png" alt="Ling Hu 微信支付"/>
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/jexo/images/alipay.png" alt="Ling Hu 支付宝"/>
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/jexo/tags/Android/" rel="tag"># Android</a>
          
            <a href="/jexo/tags/Android底层/" rel="tag"># Android底层</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/jexo/2018/04/18/Retrofit+RxJava完美封装/" rel="next" title="Retrofit+RxJava完美封装">
                <i class="fa fa-chevron-left"></i> Retrofit+RxJava完美封装
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/jexo/2018/04/18/AndroidApp启动流程/" rel="prev" title="Android App 启动流程">
                Android App 启动流程 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
      
        <div id="gitment-container"></div>
      
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/jexo/images/avatar.jpg"
                alt="Ling Hu" />
            
              <p class="site-author-name" itemprop="name">Ling Hu</p>
              <p class="site-description motion-element" itemprop="description">Android,源码解析,每天进步一点点</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/jexo/archives/">
              
                  <span class="site-state-item-count">19</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/jexo/categories/index.html">
                  <span class="site-state-item-count">9</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/jexo/tags/index.html">
                  <span class="site-state-item-count">14</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/javalong" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#linux驱动实现"><span class="nav-number">1.</span> <span class="nav-text">linux驱动实现</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#代码编译"><span class="nav-number">1.1.</span> <span class="nav-text">代码编译</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#查看驱动"><span class="nav-number">1.2.</span> <span class="nav-text">查看驱动</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#驱动测试"><span class="nav-number">2.</span> <span class="nav-text">驱动测试</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#代码编译-1"><span class="nav-number">2.1.</span> <span class="nav-text">代码编译</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HAL层实现"><span class="nav-number">3.</span> <span class="nav-text">HAL层实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#aidl实现"><span class="nav-number">4.</span> <span class="nav-text">aidl实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#service-java实现"><span class="nav-number">5.</span> <span class="nav-text">service java实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#service-jni-实现"><span class="nav-number">6.</span> <span class="nav-text">service jni 实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#注册service和jni方法"><span class="nav-number">7.</span> <span class="nav-text">注册service和jni方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#android-app调用测试"><span class="nav-number">8.</span> <span class="nav-text">android app调用测试</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Ling Hu</span>

  
</div>









        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/jexo/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/jexo/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/jexo/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/jexo/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/jexo/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/jexo/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  







<!-- LOCAL: You can save these files to your site and update links -->
    
        
        <link rel="stylesheet" href="https://aimingoo.github.io/gitmint/style/default.css">
        <script src="https://aimingoo.github.io/gitmint/dist/gitmint.browser.js"></script>
    
<!-- END LOCAL -->

    
      <style>
        a.gitment-editor-footer-tip { display: none; }
        .gitment-container.gitment-footer-container { display: none; }
      </style>
    

    
      <script type="text/javascript">
      function renderGitment(){
        var gitment = new Gitmint({
            id: getId(),
            owner: 'javalong',
            repo: 'RxJava-Operator',
            
            lang: "zh-Hans" || navigator.language || navigator.systemLanguage || navigator.userLanguage,
            
            oauth: {
            
            
                client_secret: '06b042e57b8420f5002a6407348dde078bcde761',
            
                client_id: '1b5481d6512b2f28d7a2'
            }});
        gitment.render('gitment-container');
      }

      function getId(){
            if( window.location.pathname.length>=50){
                return window.location.pathname.substr(0,50)
            }else{
                return window.location.pathname
            }
      }

      
      renderGitment();
      
      </script>
    







  





  

  

  

  
  

  

  

  

</body>
</html>
